package net.muchine.web.front.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.Locale;

import javax.validation.Valid;

import net.muchine.core.domain.user.Preference;
import net.muchine.core.domain.user.User;
import net.muchine.core.service.user.PreferenceService;
import net.muchine.core.service.user.UserService;
import net.muchine.core.service.user.exception.PasswordNotMatchedException;
import net.muchine.core.service.user.exception.UserAccountNotExistException;
import net.muchine.web.common.Messages;
import net.muchine.web.common.Pages;
import net.muchine.web.front.forms.Login;
import net.muchine.web.front.session.UserSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/account")
public class AccountController extends BaseController {
	@Autowired private UserService userService;
	@Autowired private PreferenceService prefService;
	
	@Autowired private UserSession session;
		
	private Log log = LogFactory.getLog(this.getClass());
	
	@RequestMapping(value="/login", method=RequestMethod.GET)
	public String goLogin(
			  @ModelAttribute Login login
			, @RequestParam(required=false) String backUrl 
			, ModelMap model) {
		// If user session is alive, clear the session
		if (session != null) session.clear();
		
		if (backUrl == null)
			login.setBackUrl("/");
		else
			login.setBackUrl(backUrl);
		
		return Pages.ACCOUNT_LOGIN;
	}
	
	@RequestMapping(value="/login", method=RequestMethod.POST)
	public String processLogin(
			  @ModelAttribute Login login
			, ModelMap model
			, Locale locale) {
		User user;
		
		try {
			user = userService.login(login.getUsername(), login.getPassword());
		} catch (UserAccountNotExistException e) {
			return this.handleLoginExceptions(e, model, locale);
		} catch (PasswordNotMatchedException e) {
			return this.handleLoginExceptions(e, model, locale);
		}
		
		Preference preference = prefService.findByUserSeq(user.getSeq());
		
		// Create user session
		session.initialize(user, preference);
		
		user.setLastLoginTime(new Date());
		userService.update(user);
		
		try {
			return "redirect:" + URLDecoder.decode(login.getBackUrl(), "UTF-8");
		}
		catch (UnsupportedEncodingException e) {
			log.error(e.getMessage());
			return "redirect:/";
		}
	}
	
	@RequestMapping(value="/logout")
	public String logout() {
		// Remove user session
		if (session == null) throw new IllegalStateException("User session proxy is null.");
		
		session.clear();
		return "redirect:/account/login";
	}
	
	private String handleLoginExceptions(
			  RuntimeException e
			, ModelMap model
			, Locale locale) {
		log.info(e.getClass().getSimpleName() + ": " + e.getMessage());
		
		
		model.put(Messages.ERROR, 
				this.getResourceBundle(locale).getString("Incorrect.login.credentials"));
		return Pages.ACCOUNT_LOGIN;
	}
}
